///////////////////////////////////////////////////////////////////////////////
// Name:        array.h
// Purpose:     An array container like C++ vector
// Author:      Bright Li
// Modified by:
// Created:     2018-09-04
// Version:     [0.0.1]
// RCS-ID:      $$
// Copyright:   (c) Bright Li
// Licence:
// Depend on:
///////////////////////////////////////////////////////////////////////////////

#define __WRD_DEBUG__ 1
#include <wrdc.h>
#include <wrdbg.h>

#include <stdbool.h>
#include <string.h>

const int INIT_SIZE = 4;
typedef int VectorType;

typedef struct array{
    size_t full_size;  // the max size
    size_t length;  // the current size
    // size_t elem_size;
    VectorType* data;

    void (*_constructor)(struct array*, size_t);  // Vector_t*
    void (*_destructor)(struct array*);
    // void (*element)(struct array*, size_t index);
    // void (*append)(struct array*, VectorType value);
}Vector_t;

void _constructure(Vector_t *this, size_t full_size);
void _destructure(Vector_t *this);


void _Vector_init(Vector_t *this);
void _Vector_free(Vector_t *this);
void _Vector_append(Vector_t* this, VectorType value);

#define Vector_init(array) _Vector_init(&array)
#define Vector_free(array) _Vector_free(&array)
#define Vector_append(array, value) _Vector_append(&array, value)

VectorType Vector_at(Vector_t this, size_t index);
size_t Vector_length(Vector_t this);

void _Vector_init(Vector_t *this){
    this->_constructor = _constructure;
    this->_destructor = _destructure;
    // this->element = _get_element;
    // this->append = Vector_append;
    this->_constructor(this, INIT_SIZE);
}

void _Vector_free(Vector_t *this){
    this->_destructor(this);
}

void _constructure(Vector_t *this, size_t msize){
    this->full_size = msize;
    this->length = 0;
    // 初始化数据区
    this->data = malloc(this->full_size * sizeof(VectorType));
    memset(this->data, 0, this->full_size * sizeof(VectorType));
}

void _destructure(Vector_t *this){
    // if(this == nullptr)  return;
    if(this->data == nullptr)  return;
    free(this->data);
    this->data = nullptr;
}

void _Vector_append(Vector_t* this, VectorType value){
    if(this->length >= this->full_size){
        _print("Need to realloc...\n");
        this->full_size *= 2;
        this->data = realloc(this->data, this->full_size * sizeof(VectorType));
        memset(this->data + this->length, 0, this->length * sizeof(VectorType));
    }
    this->data[this->length] = value;
    this->length += 1;
}

VectorType Vector_at(Vector_t this, size_t index){
    return this.data[index];
}

size_t Vector_length(Vector_t this){
    return this.length;
}


int main(){
    Vector_t arr;
    Vector_init(arr);

    for(int i=0; i<9; i++)
        Vector_append(arr, i+1);

    for(int i=0; i<Vector_length(arr) + 2; i++)
        printf("--> %d\n", Vector_at(arr, i));  // arr.data[0]
    Vector_free(arr);
}
